package com.nantong.admin.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.nantong.admin.annotation.PermissionRegister;
import com.nantong.admin.domain.SysPermission;
import com.nantong.admin.service.ISysPermissionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限扫描器
 * 在应用启动时扫描所有带有 @PermissionRegister 注解的控制器方法
 * 并将权限信息保存到数据库
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PermissionScanner implements CommandLineRunner {

    private final ApplicationContext applicationContext;
    private final ISysPermissionService permissionService;

    @Override
    public void run(String... args) {
        log.info("开始扫描权限注解...");
        
        // 存储所有权限信息
        List<SysPermission> allPermissions = new ArrayList<>();
        
        // 存储权限key与对象的映射，用于快速查找
        Map<String, SysPermission> permissionKeyMap = new HashMap<>();
        
        // 获取所有控制器类
        Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);
        controllers.putAll(applicationContext.getBeansWithAnnotation(Controller.class));
        
        // 扫描每个控制器类
        for (Object controller : controllers.values()) {
            Class<?> controllerClass = controller.getClass();
            
            // 处理代理类
            if (controllerClass.getName().contains("$$")) {
                controllerClass = controllerClass.getSuperclass();
            }
            
            // 获取类级别的权限注解
            PermissionRegister classPermission = AnnotationUtils.findAnnotation(controllerClass, PermissionRegister.class);
            String basePermissionKey = null;
            
            // 如果类上有权限注解，则注册类级别权限
            if (classPermission != null) {
                SysPermission permission = createPermissionFromAnnotation(classPermission);
                basePermissionKey = classPermission.key();
                allPermissions.add(permission);
                permissionKeyMap.put(permission.getPermissionKey(), permission);
            }
            
            // 获取控制器基础路径（暂时保留，可能后续会用到）
            RequestMapping requestMapping = AnnotationUtils.findAnnotation(controllerClass, RequestMapping.class);
            if (requestMapping != null && requestMapping.value().length > 0) {
                // 可以在这里使用requestMapping.value()[0]进行一些处理
            }
            
            // 扫描所有方法
            for (Method method : controllerClass.getDeclaredMethods()) {
                PermissionRegister methodPermission = AnnotationUtils.findAnnotation(method, PermissionRegister.class);
                if (methodPermission != null) {
                    SysPermission permission = createPermissionFromAnnotation(methodPermission);
                    
                    // 如果没有指定父权限，但类上有权限注解，则使用类权限作为父权限
                    if (StrUtil.isEmpty(methodPermission.parentKey()) && basePermissionKey != null) {
                        permission.setParentId(null); // 先设置为null，后面会处理父子关系
                        // 保存原始父权限key，用于后续处理
                        permission.setRemark(permission.getRemark() + "|parentKey:" + basePermissionKey);
                    } else if (StrUtil.isNotEmpty(methodPermission.parentKey())) {
                        // 保存原始父权限key，用于后续处理
                        permission.setRemark(permission.getRemark() + "|parentKey:" + methodPermission.parentKey());
                    }
                    
                    allPermissions.add(permission);
                    permissionKeyMap.put(permission.getPermissionKey(), permission);
                }
            }
        }
        
        // 保存到数据库
        if (CollUtil.isNotEmpty(allPermissions)) {
            syncPermissionsToDatabase(allPermissions);
            
            // 处理父子关系 - 在权限保存到数据库后
            updateParentChildRelationships(allPermissions, permissionKeyMap);
            
            log.info("权限扫描完成，共扫描到 {} 个权限", allPermissions.size());
        } else {
            log.info("未扫描到任何权限注解");
        }
    }
    
    /**
     * 从注解创建权限对象
     */
    private SysPermission createPermissionFromAnnotation(PermissionRegister annotation) {
        SysPermission permission = new SysPermission();
        permission.setPermissionName(annotation.name());
        permission.setPermissionKey(annotation.key());
        permission.setPermissionType(annotation.type());
        permission.setStatus(annotation.enabled() ? 1 : 0);
        permission.setRemark(annotation.remark());
        return permission;
    }
    
    /**
     * 更新父子关系
     * 在权限保存到数据库后，根据parentKey建立父子关系
     */
    private void updateParentChildRelationships(List<SysPermission> permissions, Map<String, SysPermission> permissionKeyMap) {
        // 重新从数据库获取所有权限，确保有最新的ID
        List<SysPermission> dbPermissions = permissionService.list();
        Map<String, SysPermission> dbPermissionKeyMap = dbPermissions.stream()
                .collect(Collectors.toMap(SysPermission::getPermissionKey, p -> p, (p1, p2) -> p1));
        
        List<SysPermission> toUpdate = new ArrayList<>();
        
        for (SysPermission permission : permissions) {
            String remark = permission.getRemark();
            if (remark != null && remark.contains("|parentKey:")) {
                String parentKey = remark.substring(remark.indexOf("|parentKey:") + 11);
                // 清除临时标记
                String cleanRemark = remark.substring(0, remark.indexOf("|parentKey:"));
                
                // 从数据库获取当前权限
                SysPermission dbPermission = dbPermissionKeyMap.get(permission.getPermissionKey());
                if (dbPermission != null) {
                    // 查找父权限
                    SysPermission parentPermission = dbPermissionKeyMap.get(parentKey);
                    if (parentPermission != null) {
                        // 更新父ID
                        dbPermission.setParentId(parentPermission.getPermissionId());
                        dbPermission.setRemark(cleanRemark);
                        toUpdate.add(dbPermission);
                    } else {
                        log.warn("未找到父权限：{}，权限：{}", parentKey, permission.getPermissionKey());
                    }
                }
            }
        }
        
        // 批量更新父子关系
        if (CollUtil.isNotEmpty(toUpdate)) {
            permissionService.updateBatchById(toUpdate);
            log.info("更新父子关系 {} 个", toUpdate.size());
        }
    }
    
    /**
     * 同步权限到数据库
     */
    private void syncPermissionsToDatabase(List<SysPermission> permissions) {
        // 获取数据库中已有的权限
        List<SysPermission> existingPermissions = permissionService.list();
        Map<String, SysPermission> existingPermissionMap = existingPermissions.stream()
                .collect(Collectors.toMap(SysPermission::getPermissionKey, p -> p, (p1, p2) -> p1));
        
        // 分类处理
        List<SysPermission> toInsert = new ArrayList<>();
        List<SysPermission> toUpdate = new ArrayList<>();
        
        for (SysPermission permission : permissions) {
            SysPermission existingPermission = existingPermissionMap.get(permission.getPermissionKey());
            if (existingPermission == null) {
                // 新权限，先不设置parentId，等后续处理
                permission.setParentId(null);
                toInsert.add(permission);
            } else {
                // 更新已有权限的信息，但保留原有的parentId
                permission.setPermissionId(existingPermission.getPermissionId());
                permission.setParentId(existingPermission.getParentId()); // 保留原有的父子关系
                toUpdate.add(permission);
            }
        }
        
        // 批量插入新权限
        if (CollUtil.isNotEmpty(toInsert)) {
            permissionService.saveBatch(toInsert);
            log.info("新增权限 {} 个", toInsert.size());
        }
        
        // 批量更新已有权限
        if (CollUtil.isNotEmpty(toUpdate)) {
            permissionService.updateBatchById(toUpdate);
            log.info("更新权限 {} 个", toUpdate.size());
        }
    }
}
